using System;
using System.Drawing;
using System.Web;

namespace GoodStuff.Web.Controls
{
	/// <summary>
	/// Summary description for CaptchaImageHandler.
	/// </summary>
	public class CaptchaImageHandler : IHttpHandler
	{
		#region IHttpHandler Members

		public void ProcessRequest(HttpContext context)
		{
			int width = int.Parse(context.Request.QueryString["width"]);
			int height = int.Parse(context.Request.QueryString["height"]);
			string key = context.Request.QueryString["key"];

			//retrieve the token from storage.
			string token = CaptchaImage.GetToken(key);

			context.Response.Cache.SetNoStore();
			context.Response.Cache.SetExpires(DateTime.MinValue);
			context.Response.ContentType = "image/jpeg";
				
			using(Bitmap bm = new Bitmap(width, height))
			{
				using(Graphics g = Graphics.FromImage(bm))
				{
					g.Clear(Color.White);

					RectangleF rect = new RectangleF(0,0, width, height);
					StringFormat stringFormat = new StringFormat(StringFormat.GenericDefault);
					stringFormat.Alignment = StringAlignment.Center;
					stringFormat.LineAlignment = StringAlignment.Center;

					Font font = new Font("Times New Roman", 25, FontStyle.Bold);
					g.DrawString(token, font, new SolidBrush(Color.Black), rect, stringFormat);

					//TODO: Warp this image insane
					using(Bitmap bm2 = new Bitmap(width, height))
					{
						Random rnd = new Random();
						int distortion = (rnd.Next(10)+5);
						WarpImage(bm, bm2, distortion);
						bm2.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
					}
				}
			}
		}

		private void WarpImage(Bitmap source, Bitmap dest, double distortion)
		{
			Random rnd = new Random();
			int height = dest.Height;
			int width = dest.Width;
			for (int y = 0; y < height; y++)
			{
				for (int x = 0; x < width; x++)
				{
					//TODO: Implement better stress using sin/cos and distortion.
					int newX = (int)(x + (distortion * Math.Sin(Math.PI * y / 64.0)));
					int newY = (int)(y + (distortion * Math.Cos(Math.PI * x / 64.0)));
					if (newX < 0 || newX >= width) newX = 0;
					if (newY < 0 || newY >= height) newY = 0;

					Color oldColor = source.GetPixel(newX, newY);
					if(rnd.Next(100) > 90)
					{
						oldColor = Color.FromArgb(255 - oldColor.R, 255 - oldColor.B, 255 - oldColor.G);
					}
					dest.SetPixel(x, y, oldColor);
				}
			}
		}

		public bool IsReusable
		{
			get
			{
				return false;
			}
		}

		#endregion
	}
}
